﻿using System.Security;
using System.Windows;
using System.Windows.Controls;

namespace GameView.Attachs
{
    /// <summary>
    /// 安全密码框绑定辅助类（支持 SecureString 和常规字符串）
    /// </summary>
    public static class PasswordBoxAttach
    {
        #region 常规字符串绑定

        public static readonly DependencyProperty PasswordProperty =
            DependencyProperty.RegisterAttached(
                "Password",
                typeof(string),
                typeof(PasswordBoxAttach),
                new FrameworkPropertyMetadata(
                    string.Empty,
                    FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                    OnPasswordPropertyChanged));

        public static string GetPassword(DependencyObject obj) =>
            (string)obj.GetValue(PasswordProperty);

        public static void SetPassword(DependencyObject obj, string value) =>
            obj.SetValue(PasswordProperty, value);

        #endregion 常规字符串绑定

        #region SecureString 绑定（更高安全性）

        public static readonly DependencyProperty SecurePasswordProperty =
            DependencyProperty.RegisterAttached(
                "SecurePassword",
                typeof(SecureString),
                typeof(PasswordBoxAttach),
                new FrameworkPropertyMetadata(
                    new SecureString(),
                    FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                    OnSecurePasswordChanged));

        public static SecureString GetSecurePassword(DependencyObject obj) =>
            (SecureString)obj.GetValue(SecurePasswordProperty);

        public static void SetSecurePassword(DependencyObject obj, SecureString value) =>
            obj.SetValue(SecurePasswordProperty, value);

        #endregion SecureString 绑定（更高安全性）

        #region 私有方法

        private static void OnPasswordPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is not PasswordBox passwordBox) return;

            // 解除事件避免循环
            passwordBox.PasswordChanged -= OnPasswordBoxPasswordChanged;

            // 仅在新值不同时更新（避免不必要的内存操作）
            if (passwordBox.Password != (string)e.NewValue)
            {
                passwordBox.Password = (string)e.NewValue;
            }

            // 如果启用了安全模式，同步到 SecurePassword
            if (GetUseSecureBinding(passwordBox))
            {
                UpdateSecurePassword(passwordBox);
            }

            passwordBox.PasswordChanged += OnPasswordBoxPasswordChanged;
        }

        private static void OnSecurePasswordChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is not PasswordBox passwordBox || !GetUseSecureBinding(passwordBox)) return;

            // 安全模式下不直接操作明文密码
            if (e.NewValue is SecureString newSecureString)
            {
                // 比较 SecureString 内容是否相同（简化版）
                if (SecureStringHelper.ToString(newSecureString) != passwordBox.Password)
                {
                    passwordBox.Password = SecureStringHelper.ToString(newSecureString);
                }
            }
        }

        private static void OnPasswordBoxPasswordChanged(object sender, RoutedEventArgs e)
        {
            if (sender is not PasswordBox passwordBox) return;

            // 更新绑定的 Password 属性
            SetPassword(passwordBox, passwordBox.Password);

            // 安全模式下的同步
            if (GetUseSecureBinding(passwordBox))
            {
                UpdateSecurePassword(passwordBox);
            }
        }

        private static void UpdateSecurePassword(PasswordBox passwordBox)
        {
            var secureString = new SecureString();
            foreach (char c in passwordBox.Password)
            {
                secureString.AppendChar(c);
            }
            secureString.MakeReadOnly();
            SetSecurePassword(passwordBox, secureString);
        }

        #endregion 私有方法

        #region 安全绑定模式开关

        public static readonly DependencyProperty UseSecureBindingProperty =
            DependencyProperty.RegisterAttached(
                "UseSecureBinding",
                typeof(bool),
                typeof(PasswordBoxAttach),
                new PropertyMetadata(false));

        public static bool GetUseSecureBinding(DependencyObject obj) =>
            (bool)obj.GetValue(UseSecureBindingProperty);

        public static void SetUseSecureBinding(DependencyObject obj, bool value) =>
            obj.SetValue(UseSecureBindingProperty, value);

        #endregion 安全绑定模式开关
    }

    /// <summary>
    /// SecureString 辅助工具（仅用于调试，生产环境应避免明文转换）
    /// </summary>
    internal static class SecureStringHelper
    {
        public static string ToString(SecureString secureString)
        {
            IntPtr ptr = System.Runtime.InteropServices.Marshal.SecureStringToBSTR(secureString);
            try
            {
                return System.Runtime.InteropServices.Marshal.PtrToStringBSTR(ptr);
            }
            finally
            {
                System.Runtime.InteropServices.Marshal.ZeroFreeBSTR(ptr);
            }
        }
    }
}